﻿#pragma once
#include <iostream>
#include <string>

// 指针和引用
extern void test_pointer_and_reference();


class Entity {
public:
	float x = 0.0f, y = 0.0f; // 成员变量，float 类类型，可以存储浮点数
	float speed = 1.0f; // 成员变量，float 类类型，可以存储浮点数

	float float_move(float dx, float dy) // 成员函数，相当于传入第一个参数 Entity& this
	{
		float move_x = dx * speed;
		float move_y = dy * speed;
		x += move_x;
		y += move_x;
		return sqrt(move_x * move_x + move_y * move_y); // 计算移动距离
	}
private: // 声明私有成员函数，只能在类内部使用，外部不能访问
	void say_something(const char* str) // 私有成员函数，只能在类内部使用，外部不能访问
	{
		std::cout << "say: " << str << std::endl;
	}
};

class Log {
public:
	enum Level : char {  // 枚举类型，C++ 11 之后支持枚举类型声明
		/*DEBUG,
		INFO,
		WARN,
		ERROR,
		FATAL*/
		正常 = 0,
		警告,
		错误,
	};

private:
	Level log_level = 正常; // 私有成员变量，只能在类内部使用，外部不能访问，初始化为 0 表示默认级别
	// 注意：这里 log_level 必须是 Level 类型。
public:
	void set_level(Level level) {
		log_level = level;
	}

	void normal(const char* str) {
		if (log_level == 正常)
			std::cout << "[normal]: " << str << std::endl;
	}

	void warning(const char* str) {
		if (log_level == 警告)
			std::cout << "[warning]: " << str << std::endl;
	}

	void error(const char* str) {
		if (log_level >= 错误 || log_level < 正常)
			std::cout << "[error]: " << str << std::endl;
	}

	void print_log(const char* str) {
		std::cout << "log_level: " << log_level << std::endl;
		if (log_level == 正常)
			normal(str);
		else if (log_level == 警告)
			warning(str);
		else
			error(str);
	}
};

class Player : public Entity, Log { // 继承 Entity 类和 Log 类
	// Player 类有了 Entity 类和 Log 类中的所有公有成员变量和成员函数
	// 注意，继承的顺序是从左到右，即先继承 Log 类，再继承 Entity 类；
		// 继承的类不能有相同的成员变量和成员函数名；且父类的定义必须在子类定义之前。
public: /* 公有成员函数，外部可以访问，默认是私有的（成员访问权限只能在类内部使用，
	public 声明后，外部可以访问，private 声明后，外部不能访问。）*/

	std::string name; // 成员变量，string 类类型，可以存储字符串
	std::string sex;
	int ix = 0, iy = 0;
	int i_speed = 0;
	/*Player() // 构造函数，在创建对象时调用，用来初始化对象
	{
		name = new char[10];
		sex = new char[10];
		strcpy(name, "Player1");
		strcpy(sex, "Male");
		x = 0;
		y = 0;
		speed = 1;
	}*/

	void int_move(int dx, int dy) // 成员函数，相当于传入第一个参数 Player& this
	{ // 公有成员函数，外部可以访问,在类里面定义的函数，可直接访问类中的成员变量
		ix += dx * i_speed;
		iy += dy * i_speed;
	}

private: /* 声明私有成员函数，只能在类内部使用，外部不能访问 */
	void say_something(const char* str) // 私有成员函数，只能在类内部使用，外部不能访问
	{
		std::cout << "name is " << name << " sex is " << sex << " say: "
			<< str << std::endl;
	}

};

struct Point { // 结构体，只能作为类成员变量
	float x = 0.0f, y = 0.0f;
	int speed = 0;
	//Point(int a, int b) :x(a), y(b) {} // 构造函数，在创建对象时调用，用来初始化对象
	float move(Point& stc, float dx, float dy) { // C++ 结构体成员函数（注意 C 结构体没有函数）
		float move_x = dx * speed;
		float move_y = dy * speed;
		stc.x += move_x;
		stc.y += move_x;
		return sqrt(move_x * move_x + move_y * move_y); // 计算移动距离
	}
};

extern void test_static();

extern void test_base_function();


// 宏定义
#define print_start(str) std::cout << " ----------------- " << str << " Start ------------------------\n";
#define print_end(str) std::cout << " ----------------- " << str << " End ------------------------\n\n\n";
